import 'package:flutter/widgets.dart';

abstract class LifecycleState<T extends StatefulWidget> extends State
    with WidgetsBindingObserver, RouteAware {
  static const bool _visible = true;

  static const bool _invisible = false;

  static final RouteObserver<PageRoute> routeObserver =
      RouteObserver<PageRoute>();

  @override
  T get widget => super.widget as T;

  /// 当前Widget是否可见
  bool _isVisible = _invisible;

  /// 状态改变是否来自于系统
  bool _stateChangeFromSystem = false;

  bool _isInit = false;

  @override
  void initState() {
    super.initState();
    _doCreate();
    _doResume();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    _doDestroy();
    WidgetsBinding.instance.removeObserver(this);
    routeObserver.unsubscribe(this);
    super.dispose();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute);
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    _stateChangeFromSystem = true;
    switch (state) {
      case AppLifecycleState.paused:
        _doPause();
        break;
      case AppLifecycleState.resumed:
        _doResume();
        break;
      case AppLifecycleState.inactive:
        break;
      case AppLifecycleState.detached:
        break;
    }
    _stateChangeFromSystem = false;
  }

  @override
  void didPushNext() {
    super.didPushNext();
    _doPause();
  }

  @override
  void didPopNext() {
    super.didPopNext();
    _doResume();
  }

  @override
  void didPop() {
    super.didPop();
    // _doDestroy();
  }

  @override
  void didPush() {
    super.didPush();
    _doCreate();
  }

  void _doCreate() {
    if (!_isInit) {
      _isInit = true;
      onCreate();
    }
  }

  void _doDestroy() {
    onDestroy();
  }

  void _doResume() {
    // resume有两种情况
    // 1. 由系统后台切到前台 要求之前退出后台时页面必须为可见状态
    // 2. 由其他页面切回 切回前应当为不可见状态
    if ((_stateChangeFromSystem && _isVisible) ||
        (!_stateChangeFromSystem && !_isVisible)) {
      onResume();
      _isVisible = _visible;
    }
  }

  void _doPause() {
    // 当前页面不可见则不调用该方法
    if (!_isVisible) {
      return;
    }
    // 跳转到其他页面时 置为不可见
    if (!_stateChangeFromSystem) {
      _isVisible = _invisible;
    }
    onPause();
  }

  void onCreate() {}

  /// invisible -> visible
  void onResume() {}

  /// visible -> invisible
  void onPause() {}

  void onDestroy() {}
}
